package com.gaojinqi.sys.core.shiro.util;

import cn.hutool.core.bean.BeanUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.gaojinqi.base.common.cache.KvCache;
import com.gaojinqi.base.common.util.StringUtil;
import com.gaojinqi.sys.modular.rbac.model.LoginBo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import java.util.Objects;

/**
 * 用户缓存
 *
 * @author gaojinqi
 * @version 1.0
 * @since 2020年06月05日
 */
@Component
public class UserCacheHelper {

    public static final String LOGINED_USER_ID_CACHE_KEY_PREFIX = "LOGINED_USER_ID:";
    public static final String LOGINED_USER_NAME_CACHE_KEY_PREFIX = "LOGINED_USER_NAME:";
    public static final String LOGINED_PHONE_CACHE_KEY_PREFIX = "LOGINED_USER_PHONE:";

    public static final String USER_ID_FIELD = "userId";
    public static final String USER_NAME_FIELD = "userName";
    public static final String USER_PHONE_FIELD = "phone";

    @Autowired
    private KvCache<String, String> cache;

    private String getJsonString(Object obj) {
        if (obj instanceof String) {
            return "" + obj;
        }
        // 转map，防止bean过滤字段，例如password、salt
        return JSON.toJSONString(BeanUtil.beanToMap(obj));
    }

    private String getUserIdStr(Object userId) {
        return StringUtil.asString(userId);
    }

    /**
     * 缓存用户对象
     */
    public void cache(Object value) {
        if (Objects.isNull(value)) {
            return;
        }
        String jsonStr = this.getJsonString(value);
        JSONObject object = JSONObject.parseObject(jsonStr);
        if (object != null) {
            final String userIdStr = this.getUserIdStr(object.get(USER_ID_FIELD));
            if (StringUtils.isEmpty(userIdStr)) {
                return;
            }
            // 删除旧缓存
            this.deleteByUserId(userIdStr);
            // 存入id-userBo缓存
            cache.set(LOGINED_USER_ID_CACHE_KEY_PREFIX + userIdStr, jsonStr);

            // 存入userName-id缓存
            String userName = object.getString(USER_NAME_FIELD);
            if (StringUtils.hasText(userName)) {
                cache.set(LOGINED_USER_NAME_CACHE_KEY_PREFIX + userName, userIdStr);
            }

            // 存入phone-id
            String phone = object.getString(USER_PHONE_FIELD);
            if (StringUtils.hasText(phone)) {
                cache.set(LOGINED_PHONE_CACHE_KEY_PREFIX + phone, userIdStr);
            }
        }
    }

    /**
     * 根据用户ID删除缓存
     */
    public void deleteByUserId(Object userId) {
        if (userId == null) {
            return;
        }
        final String userIdStr = this.getUserIdStr(userId);
        final String key = LOGINED_USER_ID_CACHE_KEY_PREFIX + userIdStr;
        JSONObject object = JSONObject.parseObject(cache.get(key));
        if (object != null) {
            cache.del(key);
            String userName = object.getString(USER_NAME_FIELD);
            if (userName != null) {
                cache.del(LOGINED_USER_NAME_CACHE_KEY_PREFIX + userName);
            }
            String phone = object.getString(USER_PHONE_FIELD);
            if (phone != null) {
                cache.del((LOGINED_PHONE_CACHE_KEY_PREFIX + phone));
            }
        }
    }

    /**
     * 根据用户名删除缓存
     */
    public void deleteByUserName(String userName) {
        String userIdStr = cache.get(LOGINED_USER_NAME_CACHE_KEY_PREFIX + userName);
        this.deleteByUserId(userIdStr);
    }

    /**
     * 根据用户名删除缓存
     */
    public void deleteByPhone(String phone) {
        String userIdStr = cache.get(LOGINED_PHONE_CACHE_KEY_PREFIX + phone);
        this.deleteByUserId(userIdStr);
    }

    /**
     * 获取用户json字符串信息
     */
    public String getUserStrById(Object userId) {
        if (userId == null) {
            return null;
        }
        final String userIdStr = this.getUserIdStr(userId);
        final String key = LOGINED_USER_ID_CACHE_KEY_PREFIX + userIdStr;
        return cache.get(key);
    }

    /**
     * 根据用户ID获取用户信息
     */
    public <User> User getById(Object userId, Class<User> cls) {
        String userStr = this.getUserStrById(userId);
        if (StringUtils.isEmpty(userStr)) {
            return null;
        }
        return JSON.parseObject(userStr, cls);
    }

    /**
     * 根据用户ID获取用户信息
     */
    public LoginBo getById(Object userId) {
        return this.getById(userId, LoginBo.class);
    }

    /**
     * 根据用户名获取用户信息
     */
    public <User> User getByName(String userName, Class<User> cls) {
        String userIdStr = cache.get(LOGINED_USER_NAME_CACHE_KEY_PREFIX + userName);
        String userStr = this.getUserStrById(userIdStr);
        if (StringUtils.isEmpty(userStr)) {
            return null;
        }
        return JSON.parseObject(userStr, cls);
    }

    /**
     * 根据用户名获取用户信息
     */
    public LoginBo getByName(String userName) {
        return this.getByName(userName, LoginBo.class);
    }

    /**
     * 根据联系方式获取用户信息
     */
    public <User> User getByPhone(String phone, Class<User> cls) {
        String userIdStr = cache.get(LOGINED_PHONE_CACHE_KEY_PREFIX + phone);
        String userStr = this.getUserStrById(userIdStr);
        if (StringUtils.isEmpty(userStr)) {
            return null;
        }
        return JSON.parseObject(userStr, cls);
    }

}
